package com.dutiantech.file.core;

import com.dutiantech.rambo.exception.RamboRunTimeException;
import org.apache.commons.net.ftp.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Vector;

public class NormalFTPInstance implements FileManager  {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	int connTimeOut = 13 * 1000;//超时时间
	int defaultTimeOut = 4 * 60 * 1000;//其他默认超时时间，4分钟
	
	FTPClient ftpClient = null;
	
	@Override
	public boolean login(String userName, String password, String host, int port, boolean... isPassiveMode) {
		try {
			ftpClient = new FTPClient();
			ftpClient.setDefaultTimeout(defaultTimeOut);
			ftpClient.setConnectTimeout(connTimeOut);
			ftpClient.connect(host, port);//连接FTP服务器
			ftpClient.login(userName, password);//登录
			ftpClient.setControlEncoding("UTF-8");
			try {
				if(isPassiveMode == null)//默认被动模式
					ftpClient.enterLocalPassiveMode();
				else {
					if(isPassiveMode[0])//开启被动模式
						ftpClient.enterLocalPassiveMode();
					else//开启主动模式
						ftpClient.enterLocalActiveMode();
				}
			} catch (Exception e) {
				ftpClient.enterLocalPassiveMode();//默认被动模式
			}
			int replyCode = ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(replyCode)) {
				ftpClient.disconnect();
				logger.error("ftp连接失败：" + "[" + ftpClient.getReplyCode() + "]" + ftpClient.getReplyString());
				return false;
			}
			return true;
		} catch (Exception e) {
			logger.error("ftp连接异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public boolean put(String fileName, File file) {
		try {
			checkState();
			InputStream input = new FileInputStream(file);
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);  
			boolean result = ftpClient.storeFile(fileName, input);
			input.close();
			return result;
		} catch (Exception e) {
			logger.error("ftp上传文件异常：" + e.getMessage());
			return false;
		}
	}


	@Override
	public boolean put(String fileName, byte[] body) {
		try {
			checkState();
			InputStream input = new ByteArrayInputStream(body);
			boolean result = ftpClient.storeFile(fileName, input);
			input.close();
			return result;
		} catch (Exception e) {
			logger.error("ftp上传文件异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public boolean put(String fileName, InputStream in) {
		try {
			checkState();
			boolean result = ftpClient.storeFile(fileName, in);
			in.close();
			return result;
		} catch (Exception e) {
			logger.error("ftp上传文件异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public boolean download(String savePath, String saveFileName, String remoteFileName) {
		logger.info("parts-file->savePath="+savePath);
		logger.info("parts-file->saveFileName="+saveFileName);
		logger.info("parts-file->remoteFileName="+remoteFileName);
		String filePath = savePath + File.separator + saveFileName;
		logger.info("parts-file->filePath="+filePath);
		try {
			checkState(); 
			BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(filePath));
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			boolean result = ftpClient.retrieveFile(remoteFileName, outStream);
			outStream.close();
			return result;
		} catch (Exception e) {
			logger.error("ftp下载文件异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public InputStream download(String remoteFileName) {
		try {
			checkState();
			return ftpClient.retrieveFileStream(remoteFileName);
		} catch (Exception e) {
			logger.error("ftp下载文件异常：" + e.getMessage());
			return null;
		}
	}

	@Override
	public boolean cd(String floderName) {
		try {
			checkState();
			return ftpClient.changeWorkingDirectory(floderName);
		} catch (Exception e) {
			logger.error("FTP进入目录异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public Vector<String> lsDirectory() {
		try {
			checkState();
			FTPFile[] ftpFiles = ftpClient.listFiles();
			Vector<String> result = new Vector<String>();
			for(FTPFile ftpFile : ftpFiles) {
				if(ftpFile.isDirectory())
					result.add(ftpFile.getName());
			}
			return result;
		} catch (Exception e) {
			logger.error("FTP查询所有目录异常：" + e.getMessage());
			return null;
		}
	}

	@Override
	public Vector<String> lsFiles() {
		try {
			checkState();
			FTPFile[] ftpFiles = ftpClient.listFiles();
			Vector<String> result = new Vector<String>();
			for(FTPFile ftpFile : ftpFiles) {
				if(ftpFile.isFile())
					result.add(ftpFile.getName());
			}
			return result;
		} catch (Exception e) {
			logger.error("FTP查询所有文件异常：" + e.getMessage());
			return null;
		}
	}

	@Override
	public Vector<String> lsFiles(String pathname, FTPFileFilter filter) {
		try {
			checkState();
			FTPFile[] ftpFiles = ftpClient.listFiles(pathname, filter);
			Vector<String> result = new Vector<String>();
			for(FTPFile ftpFile : ftpFiles) {
				if(ftpFile.isFile())
					result.add(ftpFile.getName());
			}
			return result;
		} catch (Exception e) {
			logger.error("FTP查询指定文件异常：" + e.getMessage());
			return null;
		}
	}

	@Override
	public boolean changeToParentDirectory() {
		try {
			checkState();
			return ftpClient.changeToParentDirectory();
		} catch (Exception e) {
			logger.error("FTP返回上层目录异常：" + e.getMessage());
			return false;
		}
	}
	
	/**
	 * 新建目录并cd进去，支持多级目录，已存在则直接cd进去
	 */
	@Override
	public boolean mkdir(String dirPath) {
		try {
			String[] paths = dirPath.split(getSeparator()) ;
			for(String path : paths ) {
				boolean cd = cd(path);
				if( cd == false ) {
					boolean make = ftpClient.makeDirectory(path);
					if(make) {
						cd = cd(path);
						if(cd == false)
							return false;
					}else
						return false;
				}
			}
			return true;
		} catch (Exception e) {
			logger.error("FTP建立多层目录时异常：" + e.getMessage());
			return false ;
		}
		
	}

	@Override
	public boolean remove(String file) {
		try {
			checkState();
			return ftpClient.deleteFile(file);
		} catch (Exception e) {
			logger.error("FTP删除文件异常：" + e.getMessage());
			return false;
		}
	}

	@Override
	public void checkState() {
		if(ftpClient == null || ftpClient.isConnected() == false)
			throw new RamboRunTimeException("FTP渠道未初始化") ;
	}

	@Override
	public void exit() {
		try {
			ftpClient.logout();
			if(ftpClient.isConnected())
				ftpClient.disconnect();
		} catch (Exception e) {
			logger.error("FTP退出异常：" + e.getMessage());
		}
	}
	
	String getSeparator() {
		if( isWindow() )
			return "\\\\";
		else
			return File.separator ;
	}
	
	boolean isWindow() {
		String osName = System.getProperty("os.name") ;
		return osName.indexOf("Window") >= 0 ;
	}


}
